/*
// 惰性单例：指的是在需要的时候才创建对象实例。
    // 本章第一节的案例
    // var Singleton = function(name) {
    //     this.name = name;
    // }

    // Singleton.getInstance = (function() {
    //     var instance = null;

    //     return function(name) {
    //         if (!instance) {
    //             instance = new Singleton(name);
    //         }

    //         return instance;
    //     }
    // })();
    // 第一章 最后的js嗅探中用到的惰性加载方案：在函数内部重写此函数，重写之后除去了嗅探是判断
    // 这里添加 AOP 面向切面编程，将与业务逻辑无关的功能抽离出来，如日志统计，安全日志等，以函数的形式动态植入到业务逻辑中
    // 如兼容ie的click事件
    // var addEvent = function(elem, type, handler) {
    //     Function.prototype.before = function(fn) {
    //         var _self = this;
    //         return function() {
    //             fn.apply(this);
    //             _self.apply(this, arguments);
    //         }
    //     }

    //     Function.prototype.after = function(fn) {
    //         var _self = this;
    //         return function() {
    //             _self.apply(this,arguments);
    //             fn.apply(this)
    //         }
    //     }

    //     if (window.addEventListener) {
    //         addEvent = function(elem, type, handler) {
    //             var transforFn = handler.before(function() {
    //                 console.log('before addEventListener')
    //             }).after(function() {
    //                 console.log('after addEventListener')
    //             })
    //             elem.addEventListener(type, transforFn, false);
    //         }
    //     } else if (window.attachEvent) {
    //         addEvent = function(elem, type, handler) {
    //             var transforFn = handler.before(function() {
    //                 console.log('before attachEvent')
    //             }).after(function() {
    //                 console.log('after attachEvent')
    //             })
    //             elem.attachEvent('on'+type, transforFn)
    //         }
    //     }

    //     addEvent(elem, type, handler);
    // }

    // var div = document.getElementById('sluggishness');
    // addEvent(div, 'click', function() {
    //     console.log('click');
    // })

    // 使用惰性单例编写弹框
    // var loginLayer = (function() {
    //     var node = null;
    //     return function() {
    //         if (!node) {
    //             var span = document.createElement('span');
    //             var div = document.createElement('div');
    //             var icon = document.createTextNode('x');
    //             var wrapper = document.querySelector('.part3-wrapper-2');
    //             span.appendChild(icon);
    //             div.className = 'fake-QQ-login';
    //             span.className = 'close-login';
    //             div.appendChild(span);
    //             wrapper.appendChild(div);

    //             span.onclick = function() {
    //                 div.style.display = 'none';
    //             }

    //             node = div;
    //         }

    //         return node;
    //     }
    // })()

    // document.querySelector('.create-layer-btn').onclick = function() {
    //     var node = loginLayer();
    //     node.style.display = 'block';
    // }
 */


// 通用惰性单例
// 上边代码缺少单一职责原则，loginLayer函数原本只想实现惰性单例的，但其中还添加了创建dom的逻辑，如果下次需要在页面中那个添加一个唯一的iframe, 或则别的，就行重新编写一次上边的函数。
// var createIframe = function() {
//     var node = null;
//     return function() {
//         if (!node) {
//             var iframe = document.createElement('iframe');
//             document.body.appendChild(iframe);
//             node = iframe;
//         }

//         return node;
//     }
// }

// 1.把不变的部分分离出来，暂不考虑创建div与iframe的差异，管理单例的逻辑其实都是一样的，可以抽象出来，用一个变量来标志是否被创建了。
var getSingle = function(fn) {
    var result;
    return function() {
        return result || (result = fn.apply(this, arguments));
    }
}
// 2. 接下来将创建登录浮框的方法，传入到getSingle中的fn里。
var createloginLayer = function() {
    var span = document.createElement('span');
    var div = document.createElement('div');
    var icon = document.createTextNode('x');
    var wrapper = document.querySelector('.part3-wrapper-2');
    span.appendChild(icon);
    div.className = 'fake-QQ-login';
    span.className = 'close-login';
    div.appendChild(span);
    wrapper.appendChild(div);

    span.onclick = function() {
        div.style.display = 'none';
    }

    return div;
}

var createIframeLayer = function() {
    var span = document.createElement('span');
    var div = document.createElement('div');
    var icon = document.createTextNode('x');
    var wrapper = document.querySelector('.part3-wrapper-3');
    var iframe = document.createElement('iframe');
    iframe.src = '//www.baidu.com';
    iframe.width ="100%";
    iframe.height ="100%";
    iframe.style.border = 0;
    span.appendChild(icon);
    div.className = 'iframe-box';
    span.className = 'close-login';
    div.appendChild(span);
    div.appendChild(iframe);
    wrapper.appendChild(div);

    span.onclick = function() {
        div.style.display = 'none';
    }

    return div;
}

// 3.使用管理单例的逻辑函数（getSingle），来创建单例
var singleLoginLayer = getSingle(createloginLayer);
var singleIframeLayer = getSingle(createIframeLayer);

// 关闭登录弹框绑定事件
document.querySelector('.create-layer-btn').onclick = function() {
    var node = singleLoginLayer();
    node.style.display = 'block';
}


document.querySelector('.create-iframe-btn').onclick = function() {
    var node = singleIframeLayer();
    node.style.display = 'block';
}
// 上边例子中，把实例对象的职责与管理单例的职责分别放在两个方法里，这两个方法可以变化相互不影响。
// var bindCloseLoginLayerEvent = getSingle(function() {
//     document.querySelector('.part3-wrapper-2 .close-login').onclick= function() {
//         var node = singleLoginLayer();
//         node.style.display = 'none';
//     }
//     return true;
// })

// var renderLoginLayer = function() {
//     singleLoginLayer();
//     bindCloseLoginLayerEvent();
// }

// renderLoginLayer()


